import operator
import time
from osv import osv, fields
from osv.orm import intersect
import tools.sql
from tools import config
from tools.translate import _
from mx import DateTime
import netsvc
from tools.amount_to_text import amount_to_text

class purchase_typeoforder(osv.osv):
    _name = 'purchase.typeoforder'
    _description = 'Purchase Type Of Order'
    _columns={
             'code':fields.char('Code',size=1),
             'name':fields.char('Name',size=64)
             }
purchase_typeoforder()

#Purchase
class purchase_order(osv.osv):
    _name = 'purchase.order'
    _inherit = 'purchase.order'
    
    def write(self, cr, uid, ids, vals, context=None):
        self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname)
        return osv.osv.write(self, cr, uid, ids,vals,context=context)
    
    def _delete_all_pol_line(self,cr,uid,ids,context):
        kdvn_pol_ids=[]
        kdvn_pol_obj =self.read(cr,uid,ids,['order_line'])
        if kdvn_pol_obj:
            kdvn_pol_ids =kdvn_pol_obj[0]['order_line'] 
        if kdvn_pol_ids:
            self.pool.get('purchase.order.line').unlink(cr,uid,kdvn_pol_ids,context)        
        return True

    def fields_get(self, cr, uid, fields=None, context=None):
        res = super(purchase_order, self).fields_get(cr, uid, fields, context)
        new_field={'search_in_line_budget':
                                        {'widget':u'char',
                                         'type':u'char',
                                         'name':u'search_in_line_budget',
                                         'select': u'1',
                                         'string':u'Budget No',
                                         'invisible':True,
                                         'visible':False,
                                         'size':128,
                                         'sql':"(Select distinct order_id from purchase_order_line pol left join product_product pp on pol.product_id=pp.id left join account_budget_post abp on kdvn_budget_id=abp.id where abp.name || ' ' || abp.code ilike chr(37) || '%s' || chr(37))"},
                   "search_in_line_project":
                                        {'widget':u'char',
                                         'type':u'char',
                                         'name':u'search_in_line_project',
                                         'select': u'1',
                                         'string':u'Job No.',
                                         'invisible':True,
                                         'visible':False,
                                         'size':128,
                                         'sql':"(Select distinct order_id from purchase_order_line pol left join kdvn_project kp on pol.project_id=kp.id where kp.name || ' ' || kp.code ilike chr(37) || '%s' || chr(37))"}}
        res.update(new_field)
        return res
    
    def create(self, cr, uid, vals, context={}):
        self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname)
        id_test=osv.osv.create(self, cr, uid, vals, context=context)        
        if 'order_payment_term_ids' in vals:
            if vals['order_payment_term_ids']==False:
                kdvn_po_payment_term_line_obj=self.pool.get('kdvn.po.payment.term.line')         
                kdvn_payment_line_id=kdvn_po_payment_term_line_obj.create(cr,uid,{'value_amount':100.0,'name':'100% Payment',
                                                         'sequence':5,'order_id':id_test})
        else:
            kdvn_po_payment_term_line_obj=self.pool.get('kdvn.po.payment.term.line')         
            kdvn_payment_line_id=kdvn_po_payment_term_line_obj.create(cr,uid,{'value_amount':100.0,'name':'100% Payment',
                                                         'sequence':5,'order_id':id_test})
        return id_test
    
    def action_packing_received(self,cr,uid,ids,*args):
        for order in self.browse(cr, uid, ids):
            picking_ids=[]
            for picking_id in order.stock_picking_ids:
                picking_ids.append(picking_id.id)
            if picking_ids:
                self.pool.get('stock.picking').write(cr,uid,picking_ids,{'state':'done'})
            self.write(cr,uid,[order.id],{'state':'delivered'})
        return True

    
    def action_picking_create(self,cr, uid, ids, *args):
        picking_id = False
        for order in self.browse(cr, uid, ids):
            if not order.special_case:
                loc_id = order.partner_id.property_stock_supplier.id
                istate = 'none'
                todo_moves = []
                for order_line in order.order_line:
                    if not order_line.product_id:
                        continue
                    if order_line.product_id.product_tmpl_id.type in ('product', 'consu'):
                        if order.location_id:
                            dest = order.location_id.id
                        else:
                            dest = False
                        if order_line.move_dest_id:
                            loc_id = order.location_id.id#self.pool.get('stock.move').write(cr, uid, [order_line.move_dest_id.id], {'location_id':order.location_id.id})
                        todo_moves.append((0,False,{
                            'name': 'PO:'+order_line.name,
                            'product_id': order_line.product_id.id,
                            'product_qty': order_line.product_qty,
                            'product_uos_qty': order_line.product_qty,
                            'product_uom': order_line.product_uom.id,
                            'product_uos': order_line.product_uom.id,
                            'date_planned': order.delivery_date,
                            'location_id': loc_id,
                            'location_dest_id': dest,
                            'picking_id': picking_id,
                            'move_dest_id': order_line.move_dest_id.id,
                            'state': 'draft',
                            'purchase_line_id': order_line.id,
                        }))
                        
                picking_id = self.pool.get('stock.picking').create(cr, uid, {
                                    'origin': order.name+((order.origin and (':'+order.origin)) or ''),
                                    'type': 'in',
                                    'address_id': order.partner_address_id.id,
                                    'invoice_state': istate,
                                    'purchase_id': order.id,
                                    'move_lines' : todo_moves,
                                })
                self.write(cr,uid,[order.id],{'state':'waiting_for_delivery'})
        return picking_id
    
    def _check_and_make_po_done(self,cr,uid,ids,context=None):
        for po_obj in self.browse(cr,uid,ids):
            if po_obj.vat_invoices_amount==po_obj.total_payment and po_obj.total_amount == po_obj.total_payment:
                wf_service = netsvc.LocalService("workflow")
                wf_service.trg_validate(uid, 'purchase.order', po_obj.id,'btn_delivered_done', cr)
        return True
    
    def action_cancel(self, cr, uid, ids, context={}):
        ok = True
        purchase_order_line_obj = self.pool.get('purchase.order.line')
        for purchase in self.browse(cr, uid, ids):
            inv = purchase.rop_ids
            if inv:# and inv.state not in ('cancel','draft'):
                raise osv.except_osv(
                    _('Could not cancel this purchase order !'),
                    _('You must first cancel all Request Of Payment attached to this purchase order.'))
        self.write(cr,uid,ids,{'state':'cancel'})
        return True
    
    def action_cancel_draft(self, cr, uid, ids, *args):
        if not len(ids):
            return False
        self.write(cr, uid, ids, {'state':'draft'})
        wf_service = netsvc.LocalService("workflow")
        for p_id in ids:
            wf_service.trg_create(uid, 'purchase.order', p_id, cr)
        return True    
    #New Code
    
    def _get_order(self, cr, uid, ids, context={}):
        result = {}
        for line in self.pool.get('purchase.order.line').browse(cr, uid, ids, context=context):
            result[line.order_id.id] = True
        return result.keys()
    
    def  _cal_untaxed(self, cr, uid, ids, field_name, arg, context):
        res = {}
        #cur_obj=self.pool.get('res.currency')
        if ids:
            order_ids ='('+ ','.join(map(str,ids))+')'
            cr.execute("Select \
                            po.id,\
                            sum(price_unit*case when state<>'done' and po.special_case=True then plan_qty else product_qty end) as price_subtotal\
                        from \
                            purchase_order po\
                        left join\
                            purchase_order_line pol on po.id = pol.order_id\
                        where po.id in (%s)\
                        group by po.id" % order_ids)
            for order_id,amount in cr.fetchall():
                res[order_id] = amount
        return res
    
    def _new_code(self,cr,uid,ids,job_id,order_type,name=False,prj=False):
        if order_type:
            po_type_obj=self.pool.get('purchase.typeoforder').browse(cr,uid,order_type)
            order_type = po_type_obj.code
        if ids:
            ids=ids[0]
        else:
            ids=0
        if not (order_type and job_id):
            val={'value':{'name':'Not Available'}}
        else:
            job_code_list=self.pool.get("kdvn.project").read(cr,uid,job_id,['code'])
            if not job_code_list:
                val={'value':{'name':'Not Available'}}
            else:
                job_code = job_code_list['code']
                project_code_len = 0
                project_code_len = len(str(job_code)+"-PO")
                
                cr.execute("Select \
                                max(substring(name from 1 for 6))::integer \
                            from \
                                purchase_order \
                            where name ilike '" + "-PO____-" + job_code.upper() + "' and id!="+str(ids))
                if cr.rowcount:
                    next_code=str(cr.fetchone()[0])
                    #raise osv.except_osv("E",next_code)
                    if next_code.isdigit():
                        next_code=str(int(next_code)+1)
                    else:
                        next_code='1'
                else:
                    next_code='1'
                val={'value':{'name':'PO' + next_code.rjust(4,'0') + "-" + job_code}}
                
            if prj and job_id:
                prj_manager = False
                prj_location = ''
                prj_pool =self.pool.get("kdvn.project")
                for prj_obj in prj_pool.browse(cr,uid,[job_id]):
                    if prj_obj.project_manager_id:
                        prj_manager = prj_obj.project_manager_id.id
                    if prj_obj.project_location_id:
                        prj_location = prj_obj.project_location_id.name
                val['value'].update({'project_manager_id':prj_manager,'delivery_to':prj_location})
            return val
    
    def _onchange_dateorder(self,cr,uid,ids,date_order,currency_id):
#        cur_obj=self.pool.get("kdvn.purchase.currency")
        #raise osv.except_osv("E","%s-%s" %(date_order,currency_id))
        
        date_order=self.pool.get('kdvn.common.function').check_date(date_order)
    
        if not date_order or not currency_id:
            return {'value':{'exrate':0.0}}
        else:
            cr.execute("Select fncompute(%s,get_default_currency(),'%s'::date,'tax_office')" % (currency_id,date_order))
            rate_obj = cr.fetchone()
            if not rate_obj:
                val = {'value':{'exrate':0.0,'date_order':date_order}}
            else:
                val={'value':{'exrate':rate_obj[0]}}
                return val
    
    def _exrate(self, cr, uid, ids, name, arg, context={}):
        res = {}
        if ids:
            cr.execute("Select id,\
                                fncompute(po.currency_id,get_default_currency(),date_order,'tax_office')\
                        from purchase_order po where id in (%s) " % ",".join(map(str, ids)))
        for po_id, rate in cr.fetchall():
            res[po_id] = rate
        for obj_id in ids:
            res.setdefault(obj_id, 0.0)
        for id in ids:
            res[id] = res.get(id, 0.0)
        return res

    def action_cancel_draft(self, cr, uid, ids, *args):
        if not len(ids):
            return False
        self.write(cr, uid, ids, {'state':'draft'})
        wf_service = netsvc.LocalService("workflow")
        for p_id in ids:
            wf_service.trg_create(uid, 'purchase.order', p_id, cr)
        return True
    
           
    def _supplier_vat_invoice_lists(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for id in ids:
            cr.execute("""Select 
                            kderp_supplier_vat_invoice_id
                        from 
                            kdvn_request_of_payment krop 
                        left join 
                            kderp_rop_supplier_vat_invoice krsvi on id=rop_id 
                        where 
                            coalesce(kderp_supplier_vat_invoice_id,0)>0 and state!='cancel'  and order_id=(%s)""" % id)
            res[id] = [x[0] for x in cr.fetchall()]
            #raise osv.except_osv("Error",res)
        return res
    
    def _get_payment_vatinvoice_info(self, cr, uid, ids, name, args, context=None):
        #tmp={'quotations':False, 'scopeofwork':False}
        res={}
        if ids:
#            tmp_list = {'vat_invoices_amount':0.0,'total_payment':0.0}
            order_ids = ','.join(map(str,ids))
            cr.execute("""Select  
                            po.id,
                            sum(coalesce(kp.actual_amount,0)) as total_payment,
                            coalesce(total_vat_amount,0) as vat_invoices_amount
                        from
                            purchase_order po
                        left join
                            (Select
                            order_id,sum(total_amount) as total_vat_amount
                            from 
                            kdvn_request_of_payment krop
                            left join 
                            kderp_rop_supplier_vat_invoice kroprir on id=rop_id
                            left join
                            kderp_supplier_vat_invoice ri on kderp_supplier_vat_invoice_id=ri.id
                            where ri.id>0 and state not in ('draft','cancel') and order_id in (%s)
                            group by order_id) vwtotal_vat_inovices on po.id = order_id
                        left join
                            kdvn_request_of_payment krop on po.id = krop.order_id and krop.state not in ('draft','cancel')
                        left join
                            kdvn_payment kp on krop.id = kp.payment_id
                        where
                            po.id in (%s)
                        group by
                            po.id,total_vat_amount""" % (order_ids,order_ids))
            for po_vat_payment_total in cr.dictfetchall():
                res[po_vat_payment_total.pop('id')]=po_vat_payment_total
        return res
     
    def _amount_after_discount(self, cr, uid, ids, name, arg, context={}):
        #(self, cr, uid, ids, name, arg, context={}):
        res={}
        if ids:
            po_ids = ",".join(map(str,ids))
            cr.execute("Select id,coalesce(amount_untaxed,0)-coalesce(discount,0) as total from purchase_order where id in (%s)" % po_ids)
        for id,total in cr.fetchall():
            res[id] = total
        return res
    
    def _get_final_amount_in_company_currency(self, cr, uid, ids, name, arg, context={}):
        typeoforder = 1
        if context:
            if 'typeoforder' in context:
                typeoforder = context['typeoforder']
        res={}
        if ids:
            po_ids = ",".join(map(str,ids))
            if typeoforder==3:
                cr.execute("""Select 
                                po.id,
                                sum(fncompute(currency_id,get_default_currency(),date_order,'tax_office')*kdoa.amount) as amount
                            from 
                                purchase_order po
                            left join
                                kderp_detail_of_advance kdoa on po.id = kdoa.order_id
                            where po.id in (%s)
                            group by
                                po.id""" % po_ids)
            else:
                cr.execute("""Select
                            po.id,
                            coalesce(fncompute(currency_id,get_default_currency(),po.date_order,'tax_office'),0)*amount_total2
                        from
                            purchase_order po where po.id in (%s)""" % po_ids)
        for id,total in cr.fetchall():
            res[id] = total
        return res
    
    def _get_po_link_id(self, cr, uid, ids, name, arg, context={}):
        res = {}
        for id in ids:
            res[id] = id
        return res
    
    def _get_budgetcode_inline(self,cr,uid,ids,name,arg,context={}):
        res = {}
        if ids:
            po_ids = ",".join(map(str,ids))
            cr.execute("Select \
                                po.id,\
                                sum(code || ',') \
                        from\
                                purchase_order po\
                        left join\
                                (Select \
                                        distinct order_id,\
                                        abp.code\
                                from\
                                        purchase_order_line pol\
                                left join\
                                        product_product pp on pol.product_id = pp.id\
                                left join\
                                        account_budget_post abp on kdvn_budget_id = abp.id) vwtemp on po.id = vwtemp.order_id\
                         where po.id in (%s) group by po.id" % po_ids)
            budgets =  cr.fetchall()
            for id,budget in budgets:
                if budget:
                    tmp = budget.strip()
                    tmp = tmp[:len(tmp)-1]
                    res[id] = tmp
                else:
                    res[id] = budget            
        return res
    
    def _new_type_def(self, cr, uid, context):
        typeoforder = 3
        if context:
            if 'typeoforder' in context:
                typeoforder = context['typeoforder']
        return typeoforder

    def _new_partner(self, cr, uid, context):
        partner_id = 1
        typeoforder=1
        if context:
            if 'typeoforder' in context:
                typeoforder = context['typeoforder']
        if typeoforder==3 or typeoforder==5:
            partner_id = 1
        else:
            partner_id =False
        return partner_id
    
    def _new_purchase_manager(self, cr, uid, context):
        cr.execute("Select manager_id from hr_department where name  ilike '%procurement%' or name ilike '%procurement%' limit 1")
        prj_manager = cr.fetchone()
        prj_manager_id=False
        if prj_manager:
            prj_manager_id= prj_manager[0]
        return prj_manager_id
    
    def _new_code_adv_other_expense(self, cr, uid, context):
        new_code = False
        if context:
            if 'action_name' in context:
                code_type = context['action_name']
                typeoforder = context['typeoforder']
                cr.execute("""Select
                                 prefix || 
                                 to_char(current_date,suffix) || 
                                 lpad((max(substring(current_code from length(prefix ||suffix)+1 for padding)::integer)+1)::text,padding,'0') as new_code
                            from
                                (Select
                                    case when 
                                    po.name is null 
                                    then 
                                    prefix || to_char(current_date,suffix) || lpad('0',padding,'0')  else po.name end as current_code,
                                    padding,
                                    suffix,
                                    prefix,current_date
                                from 
                                    ir_sequence isq
                                left join
                                    purchase_order po on po.name ilike prefix || to_char(current_date,suffix) || lpad('_',padding,'_') and typeoforder=%d
                                where 
                                    code='%s' and isq.active) vwcurrent_code
                            group by
                                padding,
                                suffix,
                                prefix,
                                current_date;""" %(typeoforder,code_type))
                new_code=cr.fetchone()[0]            
        return new_code
    
    def _new_project_id(self, cr, uid, context):
        prj_id = False
        if context:
            if 'prj_context_id' in context:
                prj_id = context['prj_context_id']
        return prj_id
    
    def _get_default_without_contract(self, cr, uid, context):
        without_contract = False
        if context:
            if 'without_contract' in context:
                without_contract = context['without_contract']
        return without_contract
    
    def _get_payment_term(self, cr, uid, ids, name, args, context=None):
        res={}
        if ids:
            for id in ids:
                res[id] = False
                order_ids = id
                cr.execute("Select \
                                po.id,\
                                pt.name as name \
                            from \
                                purchase_order po \
                            left join\
                                kdvn_po_payment_term_line pt on po.id=order_id where po.id = %s and pt.id>0 order by po.id,pt.sequence" % (order_ids))
                tmp_obj = cr.fetchall()
                if len(tmp_obj)<=1:
                    for po_id,term_name in tmp_obj:
                        res[po_id] = term_name
                else:
                    v_po_id = False
                    for po_id,term_name in tmp_obj:
                        if po_id<>v_po_id:
                            count=0
                            v_po_id = po_id
                        count+=1
                        if res[po_id]:
                            res[po_id] = res[po_id] + ", " + str(count) + ". " + term_name
                        else:
                            res[po_id] = str(count) + ". " + term_name
        return res

#Advanced Area
    
    def _get_total_advanced(self, cr, uid, ids, name, args, context={}):
        res = {}
        for po_obj in self.browse(cr,uid,ids):
            total_amount = 0.0
            for pol_obj in po_obj.order_line:
                total_amount+= (pol_obj.price_unit or 0.0) + (pol_obj.vat_amount or 0.0)
            #raise osv.except_osv("E",amount_to_text(total_amount,'in',po_obj.currency_id.spell).upper())
            res[po_obj.id]={'advance_amount':total_amount,
                            'in_word':amount_to_text(total_amount,'in',po_obj.currency_id.spell).upper()}
        return res
    
    def _get_total_advanced_details(self, cr, uid, ids, name, args, context={}):
        res = {}
        for po_obj in self.browse(cr,uid,ids):
            actual_total_amount = 0.0
            for al in po_obj.detail_advance_ids:
                actual_total_amount= actual_total_amount + (al.amount or 0.0) + (al.vat_amount or 0.0)
            res[po_obj.id]=actual_total_amount
        return res
    
    def _get_po_adv_line(self, cr, uid, ids, context={}):
        result = {}
        for line in self.pool.get('purchase.order.line').browse(cr, uid, ids, context=context):
            result[line.order_id.id] = True
        return result.keys()
    
    def action_draft_advanced(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'delivered','adv_status':'waiting'})
        wf_service = netsvc.LocalService("workflow")
        try:
            wf_service.trg_delete(uid, self._name, o['id'], cr)
        except:
            pass
        return True
    
    def action_adv_cancel(self, cr, uid, ids, *args):
        wf_service = netsvc.LocalService("workflow")
        try:
            wf_service.trg_delete(uid, self._name, o['id'], cr)
        except:
            pass
        self.write(cr, uid, ids, {'state':'cancel','adv_status':'cancel'})
        return True
    
    def action_adv_revise(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'draft','adv_status':'draft'})
        return True
    
    def action_advanced_released(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'done','adv_status':'done'})
        return True
    
    #Other Expense Area
    def action_draft_done_other_expense(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'done','exp_status':'done'})
        wf_service = netsvc.LocalService("workflow")
        try:
            wf_service.trg_delete(uid, self._name, o['id'], cr)
        except:
            pass
        return True
        
    def action_other_expense_cancel(self, cr, uid, ids, *args):
        wf_service = netsvc.LocalService("workflow")
        try:
            wf_service.trg_delete(uid, self._name, o['id'], cr)
        except:
            pass
        self.write(cr, uid, ids, {'state':'cancel','exp_status':'cancel'})
        return True
    
    def action_other_expense_revise(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'draft','exp_status':'draft'})
        return True
    
    _columns={
        'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'location_id': fields.many2one('stock.location', 'Destination',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
              
        'special_case':fields.boolean('Multi Delivery',readonly=True,states={'draft':[('readonly',False)]}),
        'without_contract':fields.boolean("Without Contract",states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'budget_codes':fields.function(_get_budgetcode_inline,method=True,type='char',size=250,string='Budget'),
        
        'combine_term':fields.function(_get_payment_term,method=True,type='text',string='Combine Term Name',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'name': fields.char('Order Reference', size=64, required=True, select=True,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'date_order':fields.datetime('Date', required=True, states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}, help="Date on which this document has been created."),
        'partner_id':fields.many2one('res.partner', 'Supplier', required=True, states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}, change_default=True),
        'partner_address_id':fields.many2one('res.partner.address', 'Address', required=True, states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'user_id': fields.many2one('res.users', 'User request',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'project_manager_id':fields.many2one('res.users','Project Manager',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        #'typeoforder': fields.selection([('m','Material'),('e','Equipment')],'Type of order',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'purchase_manager_id':fields.many2one('res.users', 'Send to',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'user_purchase':fields.many2one('res.users', 'Send to',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'effective_date': fields.date('Effective Date',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'to_date': fields.date('To',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'advance_payment': fields.float('Adv. Payment',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'progress': fields.float('Progress',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'retention':fields.float('Retention',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'detail_advance_ids':fields.one2many('kderp.detail.of.advance','order_id','Advance Detail',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'line_update': fields.boolean('Line Update',help='For checking priority line update or main update'),
        'project_id':fields.many2one('kdvn.project','Project',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'order_payment_term_ids':fields.one2many('kdvn.po.payment.term.line','order_id','Payment Term',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'incoterm_id':fields.many2one('incoterm','Incoterm',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'country_of_origin':fields.many2one('res.country','Country',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'state': fields.selection([('draft', 'Process'),
                                   #('final_quotation', 'Waiting for R.O.A.'),
                                   ('waiting_for_delivery', 'Waiting for Delivery'),
                                   ('delivered','Waiting for Payment'),
                                   ('done', 'PO Completed'),
                                   ('cancel', 'PO Canceled')],'Order Status', readonly='True'),
        #'exp_status':fields.selection([('draft','Draft'),('cancel','Cancel'),('waiting','Advanced'),('done','Released')],'Status',readonly='True'),
        
        'adv_status':fields.selection([('draft','Draft'),('cancel','Cancel'),('waiting','Advanced'),('done','Released')],'Status',readonly='True'),
        'exp_status':fields.selection([('draft','Draft'),('cancel','Cancel'),('done','Done')],'Status',readonly='True'),
        
        'typeoforder': fields.many2one('purchase.typeoforder','Type of order',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]},required=True),

        'amount_untaxed': fields.float('Untaxed Amount',digits=(16,2),readonly=True),#function(_cal_untaxed, method=True, string='Untaxed Amount',type='float',
                                  #        store={'purchase.order.line': (_get_order, None, 10)}),
        'tax_per':fields.float("VAT (%)",states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),#"VAT (%)",states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}
        'tax_amount':fields.float('Tax Amount',digits=(16,2),states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'currency_id':fields.many2one('kderp.currency','Cur.',required=True,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]},context={'typeofrate':'tax_office'}),
        'exrate':fields.function(_exrate,method=True,string="Ex.Rate",type='float'),
        'rop_ids':fields.one2many('kdvn.request.of.payment','order_id','Payment to Supplier',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        #'discount_percent':fields.float(string='Disc.(%)',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'discount':fields.float(string='Discount',readonly=True),
        'amount_total2':fields.float('After Discount',digits=(16,2),states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),#states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'final_amount_in_company_curr':fields.function(_get_final_amount_in_company_currency,type='float',string='Amount',method=True),
        
        'total_amount':fields.float('Total',readonly=True,digits=(16,2)),
        'notes': fields.text('Notes',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'origin': fields.char('Order Ref.', size=64,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        #This section field for Contract to supplier date (cts)
        'cts_date_of_contract':fields.date('Date of contract to supplier',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'cts_date_of_submitting':fields.date('Date of Submitting',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'cts_date_of_scanned':fields.date('Date of Scanned',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'cts_date_of_sending':fields.date('Date of Sending',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'cts_date_of_receiving':fields.date('Date of Receiving',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'delivery_date':fields.date('Date of Delivery',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'vat_invoice_ids':fields.function(_supplier_vat_invoice_lists,method=True,type="one2many",relation='kderp.supplier.vat.invoice',string='Supplier VAT Lists'),
        'vat_invoices_amount':fields.function(_get_payment_vatinvoice_info,string='VAT Invoices Total',method=True,type='float',digits=(16,2),multi='get_payment_info'),
        'total_payment':fields.function(_get_payment_vatinvoice_info,string='VAT Invoices Total',method=True,type='float',digits=(16,2),multi='get_payment_info'),
        
        'stock_picking_ids':fields.one2many('stock.picking','purchase_id','Delivery',readonly=True),
        
        #Attached
        'quotation_attached':fields.boolean('Quotation',readonly=1,search=2),
        'roa_comaprison_attached':fields.boolean('ROA/Comparison Sheet',readonly=1,search=2),
        'contract_attached':fields.boolean('Contract',readonly=1,search=2),
        
        'advance_amount':fields.function(_get_total_advanced,string='Adv. Amount',type='float',method=True,multi='_get_advance_from_line',
                                         store={
                                                'purchase.order.line': (_get_po_adv_line, None, 10),
                                                'purchase.order':(lambda self, cr, uid, ids, c={}: ids, None, 20)}),
        'in_word':fields.function(_get_total_advanced,string='In Word',type='char',size=256,method=True,multi='_get_advance_from_line',store={
                                                'purchase.order.line': (_get_po_adv_line, None, 10),
                                                'purchase.order':(lambda self, cr, uid, ids, c={}: ids, None, 20)}),
        'actual_advance_amount':fields.function(_get_total_advanced_details,string='Acutal Amount',type='float',method=True),        
        
        'rom_no':fields.char('R.O.M. No.',size=64,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]},help="Request of material number"),
        'delivery_to':fields.char('Delivery to',size=256,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'order_link_id':fields.function(_get_po_link_id,type='many2one',relation='purchase.order',method=True,string='Order')
        }
    _sql_constraints = [('purchase_number_unique', 'unique (name)', 'KDVN Error: The number of the purchase order must be unique !')]
    _order = "name"    
    _defaults={
              'adv_status':lambda *a:'draft',
              'exp_status':lambda *a:'draft',
              'tax_per':lambda *x:10,
              'tax_amount':lambda *x:0.0,
              'amount_total2':lambda *x:0.0,
              #'discount_percent':lambda *x:0.0,
              'advance_amount':lambda *x:0.0,
              #'adjustment_amount':lambda *x:0.0,
              'discount':lambda *x:0.0,
              #'ref_exrate':lambda *x:1.0,
              'user_id':lambda obj,cr,uid,context: uid,
              'typeoforder':_new_type_def,
              'special_case':lambda *a:False,
              'project_id':_new_project_id,
              'without_contract':_get_default_without_contract,
              'partner_id':_new_partner,
              'name':_new_code_adv_other_expense,
              'purchase_manager_id':_new_purchase_manager
              }
    
    def onchange_warehouse_id(self, cr, uid, ids, warehouse_id):
        if not warehouse_id:
            return {}
        res = self.pool.get('stock.warehouse').read(cr, uid, [warehouse_id], ['lot_input_id'])[0]['lot_input_id'][0]
        return {'value':{'location_id': res}}
    #amount_untaxed,False,amount_total2
    def _discountp_change(self,cr,uid,ids,a_untaxed,discount,final_amount,tax_per=0):
        val = {}
        if final_amount:
            discount = a_untaxed-final_amount
        if discount:
            final_amount = (a_untaxed or 0.0) - discount

        tax_amount=final_amount*tax_per/100.0        
        total_amount=tax_amount+final_amount
        val = {'tax_amount':tax_amount,'total_amount':total_amount,'discount':discount}
        #pt_osv("E",final_amount)
        return {'value':val}

    def onchange_partner_id(self, cr, uid, ids, part):
        if not part:
            return {'value':{'partner_address_id': False}}
        addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['default'])
        part = self.pool.get('res.partner').browse(cr, uid, part)    
        return {'value':{'partner_address_id': addr['default']}}

    def on_tax_percent_change(self, cr, uid, id, tax_per,amount,tax_amount=False):
        order_amount=amount or 0.0
        tax_per=tax_per or 0
        if tax_amount:
            total_amount=tax_amount+order_amount
        else:
            tax_amount=tax_per*order_amount/100.0        
            total_amount=tax_amount+order_amount
        #raise osv.except_osv("Error",order_amount)
        return {'value':{'tax_amount':tax_amount,'total_amount':total_amount}} 
    
    def action_kdvn_po_cancel(self,cr,uid,ids,*args):
        self.write(cr,uid,ids,{'state':'cancel'})
        return True
    
    def action_kdvn_po_q_sent(self,cr,uid,ids,*args):
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for pr_id in ids:
            wf_service.trg_validate(uid, 'purchase.order', pr_id,'user_confirm', cr)
        return True
    
    def action_kdvn_mur_q_material(self,cr,uid,ids,*args):
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for pr_id in ids:
            wf_service.trg_validate(uid, 'purchase.order', pr_id,'pr_confirm', cr)
        return True
    
    def action_kdvn_pc_confirmed(self,cr,uid,ids,*args):
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for pr_id in ids:
            wf_service.trg_validate(uid, 'purchase.order', pr_id,'manager_purchase_confirm', cr)
        return True
    
    def action_kdvn_confirmed(self, cr, uid, ids, context={}):
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for pr_id in ids:
            wf_service.trg_validate(uid, 'purchase.order', pr_id,'purchase_confirm', cr)
        return True

    def payment_detail_create(self,project_id,budget_id,budgetname,amount,po_term_type,adv,retention,progress):
#        if ol.product_qty<>0:
#            p_unit=ol.price_subtotal2/ol.product_qty
#        else:
#            p_unit=0.0
#        if ol.project_id:
#            project_id =ol.project_id.id
#        else:
#            project_id = prj_id
        retention_amount = retention
        progress_amount=progress
        adv_amount = adv
#        if po_term_type<>'p':
#            progress_amount =0.0
#            if po_term_type=='adv':
#                adv_amount = adv * amount/100.0
#                retention_amount = 0.0
#                progress_amount=0.0
#            else:
#                adv_amount = 0.0
#                progress_amount=0.0
#                retention_amount = amount*retention/100.0
#        else:
#            progress_amount = amount*progress/100.0
#            adv_amount = - adv * amount*progress/100.0/100.0
#            retention_amount = - retention * amount*progress/100.0/100.0
        return (0, False, {
            'project_id':project_id,
            #'product_id': a,
            #'quantity':ol.product_qty or 0.0,
            'budget_id':budget_id,
            'description':budgetname,
            #'unit':ol['product_uom'][0] or False,
            #'price_unit':p_unit,
            'amount': progress_amount,
            'advanced_amount':adv_amount,
            'retention_amount':retention_amount
        })
        
    
    def action_cancel_draft_other_expense(self, cr, uid, ids, *args):        
        self.write(cr, uid, ids, {'exp_status':'draft','state':'draft'})
        return True
    
    def action_invoice_create(self, cr, uid, ids, *args):
        res = False
        kdvn_rop_id = False
        #for o in self.browse(cr, uid, ids):
        for o in self.read(cr, uid, ids,['order_payment_term_ids',
                                         'amount_total2',
                                         'order_line',
                                         'tax_per',
                                         'tax_amount',
                                         'partner_id',
                                         'currency_id',
                                         'project_id',
                                         'id','rop_ids','notes'
                                         ]):        
            if o['rop_ids']:
                raise osv.except_osv('Warning','Request of payment already exist')
            payment_details = []
            adv_amount = 0.0
            retention_amount = 0.0
            adv = 0.0
            retention = 0.0
            progress = 0.0
            check_payment_term = False
            this_adv_per = 0
            this_retention_per =0
            
          #  raise osv.except_osv("E",self.pool.get('kdvn.po.payment.term.line').read(cr,uid,o['order_payment_term_ids'],['type','value_amount','name','due_date']))
            
            po_obj_sorted =sorted(self.pool.get('kdvn.po.payment.term.line').read(cr,uid,o['order_payment_term_ids'],['type','value_amount','name','due_date','sequence']),key=lambda k:k['sequence']) 
            for po_term in po_obj_sorted:
                check_payment_term = True
                if po_term['type']<>'p':
                    if po_term['type']=='adv':
                        this_adv_per =this_adv_per + po_term['value_amount']
                    else:
                        this_retention_per = po_term['value_amount'] + this_retention_per
                        
            if not check_payment_term:
                raise osv.except_osv("KDVN Error",'You must input payment term for this order before create payment')
            for po_term in po_obj_sorted:
                cr.execute("Select\
                              kdvn_budget_id\
                            from \
                              purchase_order_line pol\
                            left join\
                              product_product pp on product_id = pp.id\
                          where order_id=%s\
                          group by\
                              kdvn_budget_id" % (o['id']))
                #                payment_details = []
                budget_id = False
                for b_id in cr.fetchall():
                    budget_id = b_id
                total_progress = 0.0
                total_adv = 0.0
                total_retention = 0.0
                
                tax_amount = 0.0
                
                this_adv_amount = 0
                this_retention_amount = 0
                this_progress_amount = 0.0
                
                amount = o['amount_total2']
                
                #for project_id,budget_id,budgetname,amount in cr.fetchall():    
                if po_term['type']<>'p':
                    progress = 0.0
                    if po_term['type']=='adv':
                        this_adv_amount = po_term['value_amount']*amount/100.0
                        total_adv = total_adv + this_adv_amount
                        this_retention_amount = 0.0
                        #this_tax_amount = this_adv_amount * o['tax_per']/100
                    else:
                        this_adv_amount = 0.0
                        this_retention_amount = po_term['value_amount']*amount/100.0
                        total_retention = total_retention + this_retention_amount
                else:
                    progress = po_term['value_amount']*amount/100.0
                    total_progress =  total_progress + progress
                    
                    this_adv_amount  = - this_adv_per*progress/100.0
                    total_adv = total_adv + this_adv_amount
                    
                    this_retention_amount = - this_retention_per*progress/100.0
                    total_retention = this_retention_amount + total_retention
                                               
                    #payment_details.append(self.payment_detail_create(project_id,budget_id,budgetname,progress,po_term['type'],this_adv_amount,this_retention_amount,progress))
                tax_amount = (total_progress + total_adv + total_retention)*o['tax_per']/100.0
                if o['notes']:
                    new_description = po_term['name'] + "\n"+  o['notes']
                else:
                    new_description = po_term['name']
                #                if po_term['due_date']:
                #                    due_date=po_term['due_date']
                if po_term['due_date']:
                    payment = {
                        'paymentno':'',
                        'budget_id':budget_id,
                        'amount':total_progress,
                        'tax_amount':tax_amount,
                        'advanced_amount':total_adv,
                        'retention_amount':total_retention,
                        'tax_per':int(o['tax_per']) or 0,
                        'supplier_id': o['partner_id'][0],
                        'currency_id': o['currency_id'][0],
                        #'detail_ids': payment_details,
                        'order_id':o['id'], # For KDVN,
                        'project_id':o['project_id'][0],
                        'due_date':po_term['due_date'],
                        'description':new_description#po_term['name'] + "\n"+  o['notes']                        
                        }
                else:
                    payment = {
                        'paymentno':'',
                        'budget_id':budget_id,
                        'amount':total_progress,
                        'tax_amount':tax_amount,
                        'advanced_amount':total_adv,
                        'retention_amount':total_retention,
                        'tax_per':int(o['tax_per']) or 0,
                        'supplier_id': o['partner_id'][0],
                        'currency_id': o['currency_id'][0],
                        #'detail_ids': payment_details,
                        'order_id':o['id'], # For KDVN,
                        'project_id':o['project_id'][0],
                        #'due_date':po_term['due_date'],
                        'description':new_description#po_term['name'] + "\n"+  o['notes']                          
                        }
                #raise osv.except_osv("E",payment)
                kdvn_rop_id = self.pool.get('kdvn.request.of.payment').create(cr, uid, payment)
        return kdvn_rop_id

    def action_invoice_createBAK(self, cr, uid, ids, *args):
        res = False
        #for o in self.browse(cr, uid, ids):
        for o in self.read(cr, uid, ids,['order_payment_term_ids',
                                         'amount_total2',
                                         'order_line',
                                         'tax_per',
                                         'partner_id',
                                         'currency_id',
                                         'project_id',
                                         'id'
                                         ]): 
            raise osv.except_osv("E",o)       
            if o.rop_ids:
                raise osv.except_osv('Warning','Request of payment already exist')
            payment_details = []
            adv_amount = 0.0
            retention_amount = 0.0
            adv = 0.0
            retention = 0.0
            progress = 0.0
            for po_term in o.order_payment_term_ids:
                if po_term.type=='adv':
                    adv_amount = po_term.value_amount*o.amount_total2/100
                    adv = po_term.value_amount
                elif po_term.type=='re':
                    retention_amount = po_term.value_amount*o.amount_total2/100
                    retention = po_term.value_amount
                    
            for po_term in o.order_payment_term_ids:
                if po_term.type<>'p':
                    this_tax_amount = 0.0
                    this_progress_amount = 0.0
                    if po_term.type=='adv':
                        this_retention_amount = 0.0
                        this_adv_amount = adv_amount
                    else:
                        this_adv_amount = 0.0
                        this_retention_amount = retention_amount
                else:
                    progress = po_term.value_amount
                    this_tax_amount = o.tax_amount*po_term.value_amount/100.0
                    this_progress_amount = o.amount_total2*po_term.value_amount/100.0
                    this_adv_amount = - adv_amount*progress/100.0
                    this_retention_amount = - retention_amount*progress/100.0
                for ol in o.order_line:
                    if ol.product_id:
                        pr_id = ol.product_id.id
                    prj_id = o.project_id.id
                    payment_details.append(self.payment_detail_create(pr_id,ol,prj_id,po_term.type,adv,retention,progress))            
                payment = {
                    'amount':this_progress_amount,
                    'tax_amount':this_tax_amount,
                    'advanced_amount':this_adv_amount,
                    'retetion_amount':this_retention_amount,
                    'tax_per':int(o.tax_per) or 0,
                    'supplier_id': o.partner_id.id,
                    'currency_id': o.currency_id.id,
                    'detail_ids': payment_details,
                    'order_id':o.id, # For KDVN,
                    'project_id':o.project_id.id,
                    }
                #raise osv.except_osv("E",payment)
                kdvn_rop_id = self.pool.get('kdvn.request.of.payment').create(cr, uid, payment)
        return kdvn_rop_id
    
    def copy(self, cr, uid, id, default=None,context={}):
        if not default:
            default = {}
        typeoforder = False
        if context:
            if 'typeoforder' in context:
                typeoforder = context['typeoforder']
        res_user_obj=self.pool.get('res.users').read(cr,uid,uid,['name'],context)
        user_name=''
        if res_user_obj:
            user_name=str(res_user_obj['name'])
        if user_name<>'':
            user_name = " - " + user_name
        default.update({
            'rop_ids':False,
            'stock_picking_ids':False,
            'user_id':uid,
            #'order_payment_term_ids':False,
            'state':'draft',
            'exp_status':'draft',
#            'shipped':False,
#            'invoiced':False,
#            'invoice_id':False,
#            'picking_ids':[],
            'typeoforder':typeoforder,
            'name':'Not Avaiable'+user_name,
        })
        
        new_id= super(purchase_order, self).copy(cr, uid, id, default, context)
        self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname)
        return new_id
purchase_order()

class purchase_order_line(osv.osv):
    _name = 'purchase.order.line'
    _inherit = 'purchase.order.line'
    
    def name_get(self, cr, uid, ids, context={}):
        if not len(ids):
            return []
        res = []
        for record in self.read(cr, uid, ids, ['sequence','name'], context):
            name = str(record['sequence']) + ". " +  record['name']
            res.append((record['id'],name ))
        return res
    
    def isINT(self,number):
        try:
            check = int(number)
            check = True
        except:
            check = False
        return check
    
    def isFLOAT(self,number):
        if type(number).__name__=='str':
            number=number.replace(",","")
        try:            
            check = float(number)
            check = True
        except:
            check = False
        return check
    
    def search(self, cr, user, args, offset=0, limit=None, order=None,  context=None, count=False):
        if context:
            if 'order_id' in context.keys():
                order_id=context['order_id']
                cr.execute("Select \
                                    id \
                            from\
                                purchase_order_line where order_id=%s" % order_id) 
                res = cr.fetchall()
                res1=[]
                for tmp in res:
                    res1.append(tmp[0])
                var_filter=res1
                args.append(('id','in',var_filter))
        return super(purchase_order_line,self).search(cr, user, args, offset, limit, order,context, count)
    
    def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=80):
        if context:
            if 'order_id' in context.keys():
                order_id=context['order_id']
                cr.execute("Select \
                                    id \
                            from\
                                purchase_order_line where order_id=%s" % order_id) 
                res = cr.fetchall()
                res1=[]
                for tmp in res:
                    res1.append(tmp[0])
                var_filter=res1
                args = args + [('id','in',var_filter)]
        if name:
            ids=[]
            if self.isINT(name):
                ids = self.search(cr, user, [('sequence','=',name)]+ args, limit=limit, context=context)
            if not len(ids):
                ids = self.search(cr, user, [('product_id','ilike',name)]+ args, limit=limit, context=context)
            if not len(ids) and self.isFLOAT(name):
                new_name = float(name.replace(',',""))
                ids = self.search(cr, user, [('price_unit','=',new_name)]+ args, limit=limit, context=context)
            if not len(ids):                
                ids = self.search(cr, user, [('name','ilike',name)]+ args, limit=limit, context=context)
        else:
            ids = self.search(cr, user, args, limit=limit, context=context)
        result = self.name_get(cr, user, ids, context)
        return result
    
    def _get_pol_budget_info(self, cr, uid, ids, name, arg,context):
        res = {}
        if ids:
            #pol_ids = ",".join(map(str,ids))
            for id in ids:
                res[id]= 0.0#{'budget_id':False,'budgetamount':False}
            cr.execute("Select \
                            pol.id,\
                            kdvn_budget_id as budget_id\
                        from \
                            purchase_order_line pol\
                        left join \
                            purchase_order po on pol.order_id=po.id\
                        left join\
                            product_product pp on pol.product_id=pp.id\
                   where pol.id in (%s) " % ",".join(map(str,ids)))            
            for pol_id,budget_id in cr.dictfetchall():
                res[pol_id]=budget_id
        return res
    
    def _get_pol_budget_amount_info(self, cr, uid, ids, name, arg,context):
        res = {}
        if ids:
            for id in ids:
                res[id]=0.0
            cr.execute("Select \
                            pol.id,\
                            coalesce(budget_amount,0) as budgetamount\
                        from \
                            purchase_order_line pol\
                        left join \
                            purchase_order po on pol.order_id=po.id\
                        left join\
                            product_product pp on pol.product_id=pp.id\
                        left join\
                            kdvn_budget_data kbd on pol.project_id=kbd.project_id and kdvn_budget_id = budget_id\
                   where pol.id in (%s) " % ",".join(map(str,ids)))            
            for pol_id,amount in cr.fetchall():
                res[pol_id]=amount
        return res
    
    def _get_pol_total_in_company_cur(self, cr, uid, ids, name, arg,context):
        res = {}
        if ids:
            for id in ids:
                res[id]=0.0
            cr.execute("Select \
                            pol.id,\
                            ((fncompute(currency_id,get_default_currency(),date_order,'tax_office')*price_subtotal)::numeric) as amount_in_company_curr\
                        from \
                            purchase_order_line pol\
                        left join \
                            purchase_order po on pol.order_id=po.id\
                   where pol.id in (%s) " % ",".join(map(str,ids)))
            for pol_id,amount in cr.fetchall():
                res[pol_id]=amount
        return res

    def _price_unit_change(self,cr,uid,ids,qty,p_unit,p_subtotal2,plan_qty=False,special_case=False):
        change=False
        res={}
        new_qty=0
        if plan_qty and not special_case:
            new_qty = plan_qty
            qty = plan_qty
            change=True
        elif plan_qty and special_case:
            new_qty = plan_qty
            qty = 0
        discountp=0.0
        if qty==0 and plan_qty:
            new_qty = plan_qty
            vdistcount=plan_qty*p_unit - plan_qty*p_unit*discountp/100
        else:
            new_qty = qty
            vdistcount=qty*p_unit - qty*p_unit*discountp/100
        if vdistcount<>p_subtotal2:
            change=True            
        if change:            
            #cr.execute("Update purchase_order set line_update=True where id=%d;" % (order_id))            
            #cr.execute("Update purchase_order set discount=(Select sum(price_unit*product_qty)-sum(price_subtotal2) as discount from purchase_order_line where order_id=%d),discount_percent=(Select (sum(price_unit*product_qty)-sum(price_subtotal2))/sum(price_unit*product_qty)*100.0 as discount_percent from purchase_order_line where order_id=%d) where id=%d;" % (order_id,order_id,order_id))
            res={'value':{'product_qty':int(qty),'price_subtotal':new_qty*p_unit}}
        return res
    
    def _price_unit_change_adv(self,cr,uid,ids,qty,p_unit,p_subtotal2):
        change=False
        res={}
        new_qty=0
        special_case = False
        plan_qty = False
        if plan_qty and not special_case:
            new_qty = plan_qty
            qty = plan_qty
        elif plan_qty and special_case:
            new_qty = plan_qty
            qty = 0
        discountp=0.0
        if qty==0 and plan_qty:
            new_qty = plan_qty
            vdistcount=plan_qty*p_unit - plan_qtkderp.detail.of.advancey*p_unit*discountp/100
        else:
            new_qty = qty
            vdistcount=qty*p_unit - qty*p_unit*discountp/100
        if vdistcount<>p_subtotal2:
            change=True            
        if change:            
            #cr.execute("Update purchase_order set line_update=True where id=%d;" % (order_id))            
            #cr.execute("Update purchase_order set discount=(Select sum(price_unit*product_qty)-sum(price_subtotal2) as discount from purchase_order_line where order_id=%d),discount_percent=(Select (sum(price_unit*product_qty)-sum(price_subtotal2))/sum(price_unit*product_qty)*100.0 as discount_percent from purchase_order_line where order_id=%d) where id=%d;" % (order_id,order_id,order_id))
            res={'value':{'product_qty':int(qty),'price_subtotal':new_qty*p_unit,'vat_amount':new_qty*p_unit*0}}
        return res
    
    def _get_remain_budget(self, cr, uid, ids, name, arg,context):
        res ={}
        if ids:
            for id in ids:
                res[id]=0
            pol_ids = ",".join(map(str,ids))
            cr.execute("Select \
                            pol.id,\
                            coalesce(budget_amount,0)-\
                            coalesce(sum(coalesce(pol_cal.price_subtotal2,0)*fncompute(po_cal.currency_id,get_default_currency(),po_cal.date_order,'tax_office')),0) as budget_remain_thistime\
                        from\
                            purchase_order_line pol\
                        left join\
                            kdvn_project kp on pol.project_id = kp.id\
                        left join\
                            purchase_order po on pol.order_id = po.id\
                        left join\
                            product_product pp on product_id = pp.id\
                        left join\
                            kdvn_budget_data kbd on pol.project_id = kbd.project_id and kdvn_budget_id = kbd.budget_id\
                        left join\
                            (Select \
                                price_subtotal2,\
                                order_id,\
                                kdvn_budget_id,\
                                project_id\
                            from\
                                purchase_order_line pol\
                            left join\
                                product_product pp on pol.product_id = pp.id) pol_cal on pp.kdvn_budget_id = pol_cal.kdvn_budget_id and pol.project_id = pol_cal.project_id\
                        left join\
                            purchase_order po_cal on pol_cal.order_id = po_cal.id and (po.date_order>po_cal.date_order or (po.date_order=po_cal.date_order and po.name>po_cal.name)) and po_cal.state not in ('draft','cancel')\
                        where\
                            pol.id in (" + pol_ids + " )group by\
                            pol.id,budget_amount" ) #and po_cal.name like kp.code || '%'\
            for id,remain in cr.fetchall():
                res[id]= remain
        return res
    
    def product_id_change(self, cr, uid, ids, curr_id, product, qty, uom,partner_id,project_id, description,price, date_order=False,order_no=False):
        if not product:
            return {'value': {'brand_name':False}, 'domain':{'product_uom':[]}}
        prod= self.pool.get('product.product').browse(cr, uid,product)
        lang=False
#        if partner_id:
#            lang=self.pool.get('res.partner').read(cr, uid, partner_id)['lang']
#       
        #prod = self.pool.get('product.product').browse(cr, uid, product)
        chk_price = price
        prod_uom_po = prod.uom_id.id
        p_budget_id = prod.kdvn_budget_id.id
        brand_name = False
        brn = False
        for brn in prod.brand_ids:
            if not brand_name:
                brand_name = brn.brandname_id.id
            if brn.default_brand:
                brand_name = brn.brandname_id.id
        if not uom:
            uom = prod_uom_po
        if not date_order:
            date_order = time.strftime('%Y-%m-%d %H:%M:%S')
        qty = qty or 1.0
        if not chk_price:
            price=0.0
            #price_lst= prod.list_price
            p_subtotal2=qty*price
        
        if description:
            prod_name=description
        else:
            prod_name = prod.name # Default is [Code] Name prod.partner_ref 
        
     
#        res_remain=cr.fetchone()
 
        if chk_price>1:
            res = {'value': {  
                            'product_uom': uom,
                            #'name':prod_name
                            }}
        else:
            res = {'value': {'price_unit': price, #'name':prod_name,
                           # 'notes':prod.description_purchase,
                            'product_qty': int(qty),
                            'plan_qty':int(qty),
                            'product_uom': uom,
                            'price_subtotal':p_subtotal2,
                            #'budget_remain_thistime':budget_remain,
                            'brand_name':brand_name}}
        return res
    
    #Return Remaining budget   
                        
    def _cal_subtotal(self, cr, uid, ids, name, arg,context):
        res = {}
        if ids:
            pol_ids = ",".join(map(str,ids))
            cr.execute("Select \
                            pol.id,\
                            price_unit*(case when state<>'done' and po.special_case=True then plan_qty else product_qty end) as price_subtotal\
                        from \
                            purchase_order_line pol\
                        left join\
                            purchase_order po on pol.order_id = po.id\
                        where pol.id in (%s)" % pol_ids)
        for pol_id,subtotal in cr.fetchall():
            res[pol_id] =  subtotal
        return res
    #Purchase 
    
    def new_project_id(self, cr, uid, context={}):
        project_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                project_id = self.pool.get('purchase.order').read(cr,uid,[order_id],['project_id'])[0]
                if project_id:
                    try:
                        project_id = project_id['project_id'][0]
                    except:
                        project_id = False
        return project_id
    
    def new_product_id(self, cr, uid, context={}):
        prj_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                cr.execute("Select product_id from purchase_order_line pol where order_id=%s order by sequence desc limit 1" % order_id)
                #project_id = self.pool.get('purchase.order.line').read(cr,uid,[order_id],['project_id'])[0]
                new_product_obj = cr.fetchone()
                prj_id =False
                if new_product_obj:
                    prj_id = new_product_obj[0]
        return prj_id
    
    def _new_seq(self, cr, uid, context={}):
        new_seq=1
        if context:
            if 'order_id' in context:
                cr.execute("Select coalesce(max(sequence),0) from purchase_order_line where order_id=%s" % context['order_id'])
#                po_line_ids=self.search(cr,uid,[('order_id','=',context['order_id'])])
#                payments=self.read(cr,uid,po_line_ids,['sequence'],context)
                #new_seq=0
                sq = cr.fetchone()
                if sq:
                    new_seq=sq[0]
                    new_seq=new_seq+1  
        return new_seq
    
    _columns={
              
            'move_ids': fields.one2many('stock.move', 'purchase_line_id', 'Reservation', readonly=True, ondelete='set null'),
            'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
            
            'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)]),#change_default=True
            'project_id':fields.many2one('kdvn.project','Project'),
            'brand_name':fields.many2one('kdvn.brand.name','Brand'),
            'budget_id':fields.function(_get_pol_budget_info,string="Budget",type="many2one",relation="account.budget.post",method=True),              
            'product_qty': fields.integer('Qty.', required=True),#, digits=(16,2)
            'plan_qty':fields.integer('Plan Qty.'),#, digits=(16,2)
            #'price_unit': fields.float('Unit Price', required=True, digits=(16, int(config['price_accuracy']))),            
            'name': fields.char('Description', size=120, required=True),
            'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
            'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)]),
            'price_unit': fields.float('Price', required=True,digits=(16, int(config['price_accuracy']))),
            'price_subtotal': fields.float('Subtotal',readonly=True),

            'order_id': fields.many2one('purchase.order', 'Order Ref', required=True, ondelete='cascade'),
            'amount_in_company_curr':fields.function(_get_pol_total_in_company_cur,string='Amount',method=True,type='float',digits=(16,1)),#,store={'purchase.order.line':(lambda self, cr, uid, ids, c={}: ids, None, 5)}),
            'budgetamount':fields.function(_get_pol_budget_amount_info,string="Budget Amount",method=True,type="float"),
            #'discount_percent':fields.float("Disc.(%)"),
           # 'price_subtotal2':fields.float("After Discount"),
            'vat_amount':fields.float("VAT Amount"),
            #'budget_remain_thistime':fields.function(_get_remain_budget,string="Remain Amt.",type='float',method=True),
            'sequence': fields.integer('Sequence', help="The sequence field is used to order details"),         
        }
    _sql_constraints = [
        ('budget_does_not_avaiable', 'CHECK (fn_check_constraint_project_budget(order_id,project_id,product_id))',  'KDVN Error: The budget code of the project does not exists !')] 
    _order = "order_id,sequence"
    _defaults = {
        'project_id':new_project_id,
        'product_id':new_product_id,
        'sequence':_new_seq,
        'product_qty':lambda *x:0,
        'plan_qty':lambda *x:1.0,
        }

purchase_order_line()
#End of Purchase

class kderp_detail_of_advance(osv.osv):
    _name='kderp.detail.of.advance'
    _description='KDERP Detail of Advance'
    
    def new_project_id(self, cr, uid, context={}):
        project_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                project_id = self.pool.get('purchase.order').read(cr,uid,[order_id],['project_id'])[0]
                if project_id:
                    try:
                        project_id = project_id['project_id'][0]
                    except:
                        project_id = False
        return project_id
    
    def new_product_id(self, cr, uid, context={}):
        prj_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                cr.execute("Select product_id from purchase_order_line pol where order_id=%s order by sequence desc limit 1" % order_id)
                #project_id = self.pool.get('purchase.order.line').read(cr,uid,[order_id],['project_id'])[0]
                new_product_obj = cr.fetchone()
                prj_id =False
                if new_product_obj:
                    prj_id = new_product_obj[0]
        return prj_id
    
    def new_product_id(self, cr, uid, context={}):
        prj_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                cr.execute("Select product_id from kderp_detail_of_advance pol where order_id=%s limit 1" % order_id)
                #project_id = self.pool.get('purchase.order.line').read(cr,uid,[order_id],['project_id'])[0]
                new_product_obj = cr.fetchone()
                prj_id =False
                if new_product_obj:
                    prj_id = new_product_obj[0]
        return prj_id
    
    _columns = {
                'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)]),#change_default=True
                'project_id':fields.many2one('kdvn.project','Project', required=True),
                'amount':fields.float('Amount', required=True),
                'name': fields.char('Description', size=120, required=True),
                'order_id':fields.many2one('purchase.order','Order'),
                'vat_amount':fields.float("VAT Amount"),
                }
    _defaults = {
        'project_id':new_project_id,
        'product_id':new_product_id
        }
    
    def _amount_change(self,cr,uid,ids,amount):
        res={'value':{'vat_amount':amount*0}}
        return res
    
kderp_detail_of_advance()

class kderp_advance_for_budget_summary(osv.osv):
    _description='KDERP Advance for Budget Summary'
    _name = 'kderp.advance.for.budget.summary'
    _auto = False
    
    _columns = {
                'po_id':fields.many2one('purchase.order','Adv. No.',context={'typeoforder':3,'action_name':'action_advance_payment'}),
                'description':fields.text("Description"),
                'advanced_amount':fields.float("Adv. Amt."),
                'amount_in_idr':fields.float("Adv. Amt. (In Rp.)"),
                }
    def init(self,cr):
        cr.execute("""create or replace view kderp_advance_for_budget_summary as
                    Select
                        row_number() over (order by po_id,project_id,budget_id) as id,
                        *
                    from
                        (Select -- Advanced and Not Yet Released
                            po.id as po_id,
                            po.notes as description,
                            po.project_id,
                            kdvn_budget_id as budget_id,
                            sum(price_unit) as advanced_amount,
                            sum(fncompute(po.currency_id,get_default_currency(),po.date_order,'tax_office')*price_unit) as amount_in_idr
                        from
                            purchase_order po
                        left join
                            purchase_order_line pol on po.id = order_id
                        left join
                            product_product pp on pol.product_id = pp.id
                        where
                            typeoforder=3 and state not in ('draft','cancel') and
                            not exists(Select id from kderp_detail_of_advance kdoa where kdoa.order_id=po.id)
                        Group by
                            po.project_id,
                            kdvn_budget_id,
                            po.id
                        union all
                        Select -- Advanced and Released
                            po.id as po_id,
                            po.notes as description,
                            po.project_id,
                            kdvn_budget_id as budget_id,
                            sum(amount) as advanced_amount,
                            sum(fncompute(po.currency_id,get_default_currency(),po.date_order,'tax_office')*amount) as amount_in_idr
                        from
                            purchase_order po
                        left join
                            kderp_detail_of_advance kdoa on po.id = kdoa.order_id
                        left join
                            product_product pp on kdoa.product_id = pp.id
                        where
                            typeoforder=3 and state not in ('draft','cancel') and 
                            exists(Select id from kderp_detail_of_advance kdoa where kdoa.order_id=po.id)
                        Group by
                            po.project_id,
                            kdvn_budget_id,
                            po.id) vwcombined""")
kderp_advance_for_budget_summary()


class kderp_other_expense_for_budget_summary(osv.osv):
    _description='KDERP Other Expense for Budget Summary'
    _name = 'kderp.other.expense.for.budget.summary'
    _auto = False
    
    _columns = {
                'po_id':fields.many2one('purchase.order','Exp. No.', context={'typeoforder':5,'action_name':'action_other_expense'}),
                'description':fields.text("Description"),
                'exp_amount':fields.float("Adv. Amt."),
                'exp_amount_idr':fields.float("Adv. Amt. (In Rp.)"),
                }
    def init(self,cr):
        cr.execute("""create or replace view kderp_other_expense_for_budget_summary as
                    Select
                        row_number() over (order by po_id,project_id,budget_id) as id,
                        *
                    from
                        (Select
                                po.id as po_id,
                                po.notes as description,
                                po.project_id,
                                kdvn_budget_id as budget_id,
                                sum(price_unit) as exp_amount,
                                sum(fncompute(po.currency_id,get_default_currency(),po.date_order,'tax_office')*price_unit) as exp_amount_idr
                            from
                                purchase_order po
                            left join
                                purchase_order_line pol on po.id = order_id
                            left join
                                product_product pp on pol.product_id = pp.id
                            where
                                typeoforder=5 and state not in ('draft','cancel')
                            Group by
                                po.project_id,
                                kdvn_budget_id,
                                po.id) vwcombined""")
kderp_other_expense_for_budget_summary()